<

プラットフォーム ビューを使用して Flutter アプリでネイティブ iOS ビューをホストする

プラットフォーム ビューを使用すると、Flutter アプリにネイティブ ビューを埋め込むことができます。 ネイティブ ビューに変換、クリップ、不透明度を適用できるようになります。 ダーツから。

これにより、たとえばネイティブの Android および iOS SDK からの Google マップ Flutter アプリ内で直接。

iOSはハイブリッド合成のみを使用しますが、 つまりネイティブはUIViewビュー階層に追加されます。

iOS でプラットフォーム ビューを作成するには、 次の手順を使用してください。

ダーツ側では

Dart 側で、Widgetそしてビルド実装を追加します。 次の手順に示すように。

Dart ウィジェット ファイルで、次のような変更を加えます。 に示されているnative_view_example.dart:

  1. 次のインポートを追加します。

    import 'package:flutter/foundation.dart';
    import 'package:flutter/services.dart';
  2. を実装します。build()方法:

    Widget build(BuildContext context) {
      // This is used in the platform side to register the view.
      const String viewType = '<platform-view-type>';
      // Pass parameters to the platform side.
      final Map<String, dynamic> creationParams = <String, dynamic>{};
    
      return UiKitView(
        viewType: viewType,
        layoutDirection: TextDirection.ltr,
        creationParams: creationParams,
        creationParamsCodec: const StandardMessageCodec(),
      );
    }

詳細については、次の API ドキュメントを参照してください。UIKitView

ホーム側

プラットフォーム側では、Swift または Objective-C のいずれかを使用します。

ファクトリ ビューとプラットフォーム ビューを実装します。 のFLNativeViewFactoryプラットフォームビューを作成し、 プラットフォーム ビューは、UIView。 例えば、FLNativeView.swift:

import Flutter
import UIKit

class FLNativeViewFactory: NSObject, FlutterPlatformViewFactory {
    private var messenger: FlutterBinaryMessenger

    init(messenger: FlutterBinaryMessenger) {
        self.messenger = messenger
        super.init()
    }

    func create(
        withFrame frame: CGRect,
        viewIdentifier viewId: Int64,
        arguments args: Any?
    ) -> FlutterPlatformView {
        return FLNativeView(
            frame: frame,
            viewIdentifier: viewId,
            arguments: args,
            binaryMessenger: messenger)
    }

    /// Implementing this method is only necessary when the `arguments` in `createWithFrame` is not `nil`.
    public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
          return FlutterStandardMessageCodec.sharedInstance()
    }
}

class FLNativeView: NSObject, FlutterPlatformView {
    private var _view: UIView

    init(
        frame: CGRect,
        viewIdentifier viewId: Int64,
        arguments args: Any?,
        binaryMessenger messenger: FlutterBinaryMessenger?
    ) {
        _view = UIView()
        super.init()
        // iOS views can be created here
        createNativeView(view: _view)
    }

    func view() -> UIView {
        return _view
    }

    func createNativeView(view _view: UIView){
        _view.backgroundColor = UIColor.blue
        let nativeLabel = UILabel()
        nativeLabel.text = "Native text from iOS"
        nativeLabel.textColor = UIColor.white
        nativeLabel.textAlignment = .center
        nativeLabel.frame = CGRect(x: 0, y: 0, width: 180, height: 48.0)
        _view.addSubview(nativeLabel)
    }
}

最後にプラットフォームビューを登録します。 これはアプリまたはプラグインで実行できます。

アプリの登録については、 アプリを変更するAppDelegate.swift:

import Flutter
import UIKit

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)

        weak var registrar = self.registrar(forPlugin: "plugin-name")

        let factory = FLNativeViewFactory(messenger: registrar!.messenger())
        self.registrar(forPlugin: "<plugin-name>")!.register(
            factory,
            withId: "<platform-view-type>")
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

プラグインの登録については、 プラグインのメインファイルを変更する (例えば、FLPlugin.swift):

import Flutter
import UIKit

class FLPlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
        let factory = FLNativeViewFactory(messenger: registrar.messenger())
        registrar.register(factory, withId: "<platform-view-type>")
    }
}

Objective-C で、ファクトリとプラットフォーム ビューのヘッダーを追加します。 たとえば、次のようにFLNativeView.h:

#import <Flutter/Flutter.h>

@interface FLNativeViewFactory : NSObject <FlutterPlatformViewFactory>
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
@end

@interface FLNativeView : NSObject <FlutterPlatformView>

- (instancetype)initWithFrame:(CGRect)frame
               viewIdentifier:(int64_t)viewId
                    arguments:(id _Nullable)args
              binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;

- (UIView*)view;
@end

ファクトリ ビューとプラットフォーム ビューを実装します。 のFLNativeViewFactoryプラットフォームビューを作成し、 プラットフォーム ビューは、UIView。例えば、FLNativeView.m:

#import "FLNativeView.h"

@implementation FLNativeViewFactory {
  NSObject<FlutterBinaryMessenger>* _messenger;
}

- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
  self = [super init];
  if (self) {
    _messenger = messenger;
  }
  return self;
}

- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
                                   viewIdentifier:(int64_t)viewId
                                        arguments:(id _Nullable)args {
  return [[FLNativeView alloc] initWithFrame:frame
                              viewIdentifier:viewId
                                   arguments:args
                             binaryMessenger:_messenger];
}

/// Implementing this method is only necessary when the `arguments` in `createWithFrame` is not `nil`.
- (NSObject<FlutterMessageCodec>*)createArgsCodec {
    return [FlutterStandardMessageCodec sharedInstance];
}

@end

@implementation FLNativeView {
   UIView *_view;
}

- (instancetype)initWithFrame:(CGRect)frame
               viewIdentifier:(int64_t)viewId
                    arguments:(id _Nullable)args
              binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
  if (self = [super init]) {
    _view = [[UIView alloc] init];
  }
  return self;
}

- (UIView*)view {
  return _view;
}

@end

最後にプラットフォームビューを登録します。 これはアプリまたはプラグインで実行できます。

アプリの登録については、 アプリを変更するAppDelegate.m:

#import "AppDelegate.h"
#import "FLNativeView.h"
#import "GeneratedPluginRegistrant.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

   NSObject<FlutterPluginRegistrar>* registrar =
      [self registrarForPlugin:@"plugin-name"];

  FLNativeViewFactory* factory =
      [[FLNativeViewFactory alloc] initWithMessenger:registrar.messenger];

  [[self registrarForPlugin:@"<plugin-name>"] registerViewFactory:factory
                                                          withId:@"<platform-view-type>"];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

プラグインの登録については、 メインのプラグインファイルを変更する (例えば、FLPlugin.m):

#import <Flutter/Flutter.h>
#import "FLNativeView.h"

@interface FLPlugin : NSObject<FlutterPlugin>
@end

@implementation FLPlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FLNativeViewFactory* factory =
      [[FLNativeViewFactory alloc] initWithMessenger:registrar.messenger];
  [registrar registerViewFactory:factory withId:@"<platform-view-type>"];
}

@end

詳細については、次の API ドキュメントを参照してください。

  • FlutterPlatformViewFactory
  • FlutterPlatformView
  • PlatformView

それを一緒に入れて

実装する際には、build()Dartのメソッド、 使用できます9a7736c7-83e4-4dd0-b787-0dbfaf43207bプラットフォームを検出し、どのウィジェットを使用するかを決定します。

Widget build(BuildContext context) {
  // This is used in the platform side to register the view.
  const String viewType = '<platform-view-type>';
  // Pass parameters to the platform side.
  final Map<String, dynamic> creationParams = <String, dynamic>{};

  switch (defaultTargetPlatform) {
    case TargetPlatform.android:
    // return widget on Android.
    case TargetPlatform.iOS:
    // return widget on iOS.
    default:
      throw UnsupportedError('Unsupported platform view');
  }
}

パフォーマンス

Flutter のプラットフォーム ビューにはパフォーマンスのトレードオフが伴います。

たとえば、典型的な Flutter アプリでは、Flutter UI は次のようになります。 専用のラスター スレッドで構成されます。 これにより、Flutter アプリが高速になります。 メインプラットフォームのスレッドがブロックされることはほとんどないためです。

プラットフォーム ビューがハイブリッド構成でレンダリングされる場合、 Flutter UI はプラットフォーム スレッドから構成されます。 プラットフォームのスレッドが他のタスクと競合する OS やプラグインのメッセージの処理など。

iOS PlatformView が画面上にある場合、画面のリフレッシュ レートは次のようになります。 レンダリングのジャンクを避けるために 80fps に制限されています。

複雑なケースの場合、使用できるテクニックがいくつかあります パフォーマンスの問題を軽減します。

たとえば、プレースホルダー テクスチャを使用しながら、 Dartでアニメーションが起こっています。 言い換えれば、プラットフォーム ビューのレンダリング中にアニメーションが遅い場合、 次に、ネイティブ ビューのスクリーンショットを取得し、それをテクスチャとしてレンダリングすることを検討してください。

構成の制限

iOS プラットフォーム ビューを作成する場合には、いくつかの制限があります。

  • ShaderMaskColorFilteredウィジェットはサポートされていません。
  • BackdropFilterウィジェットがサポートされており、 ただし、使用方法にはいくつかの制限があります。 詳細については、こちらをご覧ください。iOS プラットフォーム ビュー背景フィルターぼかし設計ドキュメント。